﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Activation;
using MusicStore.Data.Repository;
using MusicStore.Entities;
using MusicStore.Entities.Faults;
using MusicStore.WebService.Helpers;

namespace MusicStore.WebService
{
	// NOTE: If you change the class name "MusicStoreService" here, you must also update the reference to "MusicStoreService" in Web.config and in the associated .svc file.
	[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
	public class MusicStoreService : IMusicStoreService
	{
		readonly IAlbumRepository _albumRepository;

		public MusicStoreService() : this (new AlbumRepository())
		{
		}

		public MusicStoreService(IAlbumRepository albumRepository)
		{
			_albumRepository = albumRepository;
		}

		public string GetData(int value)
		{
			return string.Format("You entered: {0}", value);
		}

		public CompositeType GetDataUsingDataContract(CompositeType composite)
		{
			if (composite.BoolValue)
			{
				composite.StringValue += "Suffix";
			}
			return composite;
		}

		public void ThrowException()
		{
			throw GetFaultException("Test Exception");
		}

		private static FaultException<FaultDetail> GetFaultException(string message)
		{
			FaultDetail exDetail = new FaultDetail();
			exDetail.Message = message;
			return new FaultException<FaultDetail>(exDetail);
		}

		public List<AlbumSummary> GetAlbums()
		{
			try
			{
				List<AlbumSummary> summaries = _albumRepository.AlbumSummaries().ToList();
				PostProcessToAddTestCovers(summaries);
				return summaries;
			}
			catch (Exception)
			{
				throw GetFaultException("Error Getting the Album Summaries");
			}
		}

		public List<AlbumSummary> SearchAlbums(string text)
		{
			try
			{
				List<AlbumSummary> summaries = _albumRepository.AlbumSummaries().Search(text).ToList();
				PostProcessToAddTestCovers(summaries);
				return summaries;
			}
			catch (Exception)
			{
				throw GetFaultException("Error Searching the Albums");
			}
		}

		public Album GetAlbum(int id)
		{
			try
			{
				Album album = _albumRepository.Albums().ByAlbumId(id);
				album.Image = GetAlbumPreviewUri(album.Id);
				return album;
			}
			catch (Exception)
			{
				throw GetFaultException("Error Getting the Album with id:" + id);
			}
		}

		public string GetAlbumPreviewUri(int id)
		{
			return ImageHelper.BuildImageUri(System.Web.HttpContext.Current, id);
		}

		public int Save(Album album)
		{
			// we need to get the album, if there's one we need to sync the data
			// otherwise we can just save the new album instance we have here (cause it is a newely created album)
			// but since we use nhibernate we can try to call the save or update directly and he will handle the operation
			// based on the mapping it has
			try
			{
				_albumRepository.Save(album);
				_albumRepository.Flush();
				return album.Id;
			}
			catch (Exception)
			{
				throw GetFaultException("Error Saving the Album:" + album);
			}
		}

		public void Delete(int id)
		{
			try
			{
				var a = _albumRepository.Albums().ByAlbumId(id);
				_albumRepository.Delete(a);
				_albumRepository.Flush();
			}
			catch (Exception)
			{
				throw GetFaultException("Error Deleting the Album:" + id);
			}
		}

		private List<T> GetList<T>()
		{
			try
			{
				return _albumRepository.List<T>().ToList();
			}
			catch (Exception)
			{
				throw GetFaultException("Error Getting the List of:" + typeof(T).Name);
			}
		}

      public List<Genre> GetGenres()
		{
      	return GetList<Genre>();
		}

		public List<Author> GetAuthors()
		{
			return GetList<Author>();
		}

		public List<Label> GetLabels()
		{
			return GetList<Label>();
		}

		public List<Author> GetAuthors(string startWidth)
		{
			return _albumRepository.List<Author>().Where(a => a.Name.StartsWith(startWidth)).ToList();
		}

		public List<Label> GetLabels(string startWidth)
		{
			return _albumRepository.List<Label>().Where(l => l.Name.StartsWith(startWidth)).ToList();
		}

		private static void PostProcessToAddTestCovers(IEnumerable<AlbumSummary> albumSummaries)
		{
			foreach (var albumSummary in albumSummaries)
			{
				albumSummary.Image = ImageHelper.BuildImageUri(System.Web.HttpContext.Current, albumSummary.Id);
			}
		}

	}
}
